<template>
	<view class="scroll-view" @touchstart="onTouchStart" @touchmove="onTouchMove" @touchend="onTouchEnd">
		<view class="view-list" :style="scrollOffsetStyle">
			<view class="list-item" v-for="(item,index) in suffixItems" :key="index+'left'"
				:style="(index-excessCount == curIndex && itemSelectBig) ? itemParentSelectStyle : itemParentNomalStyle"
				@click="onItemClick(-excessCount,index)">

				<view class="item" :class="{'item-checked ':itemSelectBig && (curIndex == index - excessCount)}"
					:style="itemAnimateStyle">
					<slot :item="item" :index="index"></slot>
				</view>
			</view>
			<view class="list-item" v-for="(item,index) in itemsDataList"
				:style="(index == curIndex && itemSelectBig) ? itemParentSelectStyle : itemParentNomalStyle"
				@click="onItemClick(index)" :key="index">

				<view class="item" :class="{'item-checked ':itemSelectBig && (index == curIndex)}" :style="itemAnimateStyle">
					<slot :item="item" :index="index"></slot>
				</view>
			</view>

			<view class="list-item" v-for="(item,index) in prefixItems" :key="index + 'right'"
				:style="(itemsDataList.length + index == curIndex && itemSelectBig) ? itemParentSelectStyle : itemParentNomalStyle"
				@click="onItemClick(itemsDataList.length,index)">

				<view class="item" :class="{'item-checked ':itemSelectBig && (curIndex == index + itemsDataList.length)}" :style="itemAnimateStyle">
					<slot :item="item" :index="index"></slot>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	 let lottrypoolCount = 30;

	export default {

		props: {
			aTime:{
				type: [Number],
				default: 0.2
			},
			//每个元素的宽度 单位px
			itemW: {
				type: [Number],
				default: uni.upx2px(200)
			},
			//每个元素的高度, 单位px
			itemH: {
				type: [Number],
				default: uni.upx2px(200)
			},
			//两边各多出几个item
			excessCount: {
				type: [Number],
				default: 4
			},
			items: {
				type: Array,
				default: []
			},
			//选中的item 是否有放大效果
			itemSelectBig: {
				type: [Boolean],
				default: false
			},
			//是否禁止触摸滑动
			disableTouch: {
				type: [Boolean],
				default: false
			},
			//是否是抽奖
			isLottry:{
				type:[Boolean],
				default:false
			}
		},
		data() {
			return {
				scrolloffset: 0,
				aniTime: this.aTime,
				curIndex: 0,

				isTouch: false,
				isMove: false,
				startX: 0,
				endX: 0,
				prizePoolItems:[],//奖池数据
				itemsData: []
			}
		},
		computed: {
			itemsDataList() {
				 this.itemsData =this.items || [];
				return this.itemsData
			},
			// 初始偏移量
			startOffset() {
				let itemScle = 1;
				if (this.itemSelectBig) {
					itemScle = 1.4
				}
				return uni.upx2px(375) - this.itemW * itemScle / 2 - this.excessCount * this.itemW;
			},
			scrollOffsetStyle() {
				// 注意：translateX 的单位得用px，不然会有误差，不知道什么原因，不信你可以试试。把所有单位换成rpx
				return `transition: all ${ this.isTouch ? 0 :this.aniTime }s ${this.isLottry?'ease-in-out':'linear'};transform: translateX(${this.scrolloffset}px);`
			},
			//后缀部分
			prefixItems() {
				return this.items.slice(0, this.excessCount);
			},
			//前缀部分
			suffixItems() {
				return this.items.slice(this.items.length - this.excessCount, this.items.length);
			},
			//选中的item容器（放大1.4）
			itemParentSelectStyle() {
				return `width:${this.itemW * 1.4}px;height:${this.itemH*1.4}px;transition: all ${this.aniTime}s linear;`
			},
			//正常情况下的容器
			itemParentNomalStyle() {
				return `width:${this.itemW}px;height:${this.itemH}px;transition: all ${this.aniTime}s linear;`
			},
			itemAnimateStyle() {
				return `transition: all ${this.aniTime}s linear;transform-origin: bottom center;`
			}
		},
		
		mounted() {
			if(this.isLottry){
				this.initLottryData();
			}else{
				this.scrolloffset = this.startOffset;
			}
		},
		methods: {
			onTouchStart(e) {
				if (this.disableTouch) return
				let x = e.changedTouches[0].clientX;
				//console.log("触摸开始=====",x);

				this.isTouch = true;
				// 记录之前的偏移量
				this.oldOffset = this.scrolloffset;
				this.startX = x;
			},
			onTouchMove(e) {
				if (this.disableTouch) return
				this.isMove = true;
				let x = e.changedTouches[0].clientX;
				//console.log("触摸结束=====",x);
				this.endX = x;
				this.scrolloffset = this.oldOffset + this.endX - this.startX;
			},
			onTouchEnd(e) {
				if (this.disableTouch || this.isLottry) return
				let x = e.changedTouches[0].clientX;
				//console.log("触摸结束=====",x);
				if (this.isMove && !this.isLottry) {
					//只有移动的时候才会对不齐中间，点击item的时候不执行这个
					this.moveItemAfterToCenter();
				}
				this.isTouch = false;
				this.isMove = false;

			},
			//针对触摸后屏幕中心点没有和item的中心对齐，使其对齐
			moveItemAfterToCenter() {
				//1、计算出当前偏移量在哪个item上，求curIndex 
				//this.scrolloffset = startOffset - realIndex * this.itemW;
				//根据上面的公式计算realIndex  = (startOffset - this.scrolloffset)/this.itemW; 
				//因为偏移量是指向中心位置的，所以这个realIndex是中间位置，也就是 realIndex ± 0.5 都是这个item,所以必须是四舍五入，要不然就要再减去 this.itemW/2，
				//最后公式是realIndex  = (startOffset - this.scrolloffset - this.itemW/2)/this.itemW;

				//四舍五入的情况是 let curIndex =  Math.round((startOffset - this.scrolloffset) / this.itemW);
				//下面是向上取整
				let curIndex = Math.ceil((this.startOffset - this.scrolloffset - this.itemW / 2) / this.itemW);
				this.curIndex = curIndex;
				console.log("计算得到当前索引：", curIndex);
				this.scrolloffset = this.startOffset - curIndex * this.itemW;
				this.loopOffset(curIndex);
			},
			onItemClick(startIndex, index) {
				if (this.disableTouch) {
					return;
				}
				let realIndex = startIndex;
				if (startIndex > 9) {
					realIndex = startIndex + index;
				}
				if (startIndex < 0) {
					realIndex = startIndex + index;
				}
				this.curIndex = realIndex;
				this.scrolloffset = this.startOffset - realIndex * this.itemW;

				//console.log("偏移量：",this.scrolloffset);
				this.loopOffset(realIndex);
			},
			//无限循环的关键
			loopOffset(realIndex) {
				if (realIndex > this.items.length - 1 || realIndex < 0) {
					let rindex = 0;
					if (realIndex > this.items.length - 1) { //后缀item， 需要回到真正的偏移量
						rindex = realIndex - this.items.length;
					} else { //前缀item，偏移量需要指向最后边的那几个item
						rindex = this.items.length + realIndex;
					}
					setTimeout(() => {
						console.log("归正：");
						//点击后有个动画时间，过了动画后以不可察觉的无动画方式使偏离量回正。
						this.aniTime = 0;
						this.scrolloffset = this.startOffset - rindex * this.itemW;
						this.curIndex = rindex;

						setTimeout(() => {
							console.log("归正结束");
							this.aniTime = this.aTime;
						}, 100) //执行上一句需要时间，等待一会儿再把动画时间复原
					}, 300)
				} else {
					this.curIndex = realIndex;
				}
			},
			//设置数据
			initLottryData(winPrizeIndex){
				// 随机一个数作为奖品（应该注意的是，抽奖前奖品是什么就已经注定，滚动只是一个效果，奖品是随机也确实没啥大问题。））
				let winPrizeItemIndex = winPrizeIndex || parseInt(Math.random()*this.items.length);
				console.log(winPrizeItemIndex, 'winPrizeItemIndex')
				
				let prizeItem = this.items[winPrizeItemIndex];//当前奖品
				let listLength = this.items.length;
				
				let prizePoolItems = [];
				if(this.prizePoolItems.length == 0){ //第一次，不用考虑当前屏幕显示的是哪几个奖品
					console.log("第一次抽奖：");
					while(prizePoolItems.length<lottrypoolCount){
						if(prizePoolItems.length == lottrypoolCount -3){
							//将本次奖品放入奖品池中
							prizePoolItems.push(prizeItem);
						}else{
							//从商品池中随机选一个
							const randomIndex = parseInt(Math.random()*listLength);
							prizePoolItems.push(this.items[randomIndex]);
						}
					}
				}else{
					
					//需要上一次抽奖的后三个，放在这次奖品池数据的头三个，形成视觉误差，
					prizePoolItems.push(this.prizePoolItems[this.prizePoolItems.length -5]);
					prizePoolItems.push(this.prizePoolItems[this.prizePoolItems.length -4]);
					prizePoolItems.push(this.prizePoolItems[this.prizePoolItems.length -3]);
					prizePoolItems.push(this.prizePoolItems[this.prizePoolItems.length -2]);
					prizePoolItems.push(this.prizePoolItems[this.prizePoolItems.length -1]);
					
					while(prizePoolItems.length<lottrypoolCount){
						if(prizePoolItems.length == lottrypoolCount -3){
							//将本次奖品放入奖品池中
							prizePoolItems.push(prizeItem);
						}else{
							//从商品池中随机选一个
							const randomIndex = parseInt(Math.random()*listLength);
							prizePoolItems.push(this.items[randomIndex]);
						}
					}
				}
				//记录上一次的商品池进神
				this.prizePoolItems = prizePoolItems;
				
				this.items = prizePoolItems;
				console.log("奖品池数据：",prizePoolItems);
				this.aniTime = 0;
				this.scrolloffset = this.startOffset - 2 * this.itemW;
				setTimeout(()=>{
					this.aniTime = this.aTime;
				},100)
			},
			startDraw(winPrizeIndex){
				if(this.drawTimer){
					uni.showToast({
						title:"正在抽奖，请稍后。。。",
						icon:"none"
					})
					return
				}
				
				this.scrolloffset = this.startOffset - 27 * this.itemW;
				this.drawTimer = setTimeout(()=>{
					clearTimeout(this.drawTimer);
					this.drawTimer = null;
					this.initLottryData(winPrizeIndex);
					// 抽奖结束回调
					this.$emit("endDraw",winPrizeIndex);
				},this.aniTime*1000);
			}
		}
	}
</script>

<style lang="scss">
	.scroll-view {
		position: relative;
		width: 750rpx;
		min-height: 300rpx;
		padding: 10rpx;
		overflow: hidden;
		display: flex;
		align-items: center;
		flex-direction: row;
		box-sizing: border-box;
	}

	.view-list {
		position: relative;
		display: flex;
		height: 100%;
		flex-wrap: nowrap;
		flex-direction: row;
		align-items: center;
		box-sizing: border-box;

		.list-item {
			position: relative;
			display: flex;
			justify-content: center;
			align-items: center;
			box-sizing: border-box;
			transform-origin: bottom center;


			// .item—normal {
			// 	box-sizing: border-box;
			// 	transform-origin: bottom center;
			// }
				.item{
					width: 100%;
					height: 100%;
					margin: 0 50rpx;
				}
			.item-checked {
				background-color: gold;
				transform: scale(1.4);
			}

			.item-center-line {
				position: absolute;
				height: 100%;
				width: 1rpx;
				background-color: green;
				box-sizing: border-box;
			}

		}
	}
</style>
